import svgCaptcha from 'svg-captcha';
import { v4 as uuidv4 } from 'uuid';
import {redisConfig} from '@/config/redis';
import NodeCache from 'node-cache';
import redisClient from '@/config/redis';

// 验证码配置
const CAPTCHA_CONFIG = {
  // 验证码宽度
  width: 160,
  // 验证码高度
  height: 60,
  // 验证码长度
  size: 4,
  // 干扰线条数
  noise: 3,
  // 验证码字符集
  charPreset: 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789',
  // 验证码颜色
  color: true,
  // 背景颜色
  background: '#f0f0f0',
  // 过期时间（秒）
  expire: 120,
  // 允许尝试次数
  maxAttempts: 5
};

// 创建本地缓存
let localCache: NodeCache | null = null;

if (!redisConfig.enabled) {
  // 使用本地缓存
  localCache = new NodeCache({
    stdTTL: CAPTCHA_CONFIG.expire,
    checkperiod: 60
  });
}

class CaptchaUtil {
  /**
   * 生成验证码
   * @returns 验证码信息
   */
  static async generate() {
    // 创建验证码
    const captcha = svgCaptcha.create({
      size: CAPTCHA_CONFIG.size,
      width: CAPTCHA_CONFIG.width,
      height: CAPTCHA_CONFIG.height,
      fontSize: 50,
      ignoreChars: '0oO1iIl',
      noise: CAPTCHA_CONFIG.noise,
      color: CAPTCHA_CONFIG.color,
      background: CAPTCHA_CONFIG.background
    });

    // 生成唯一标识
    const uuid = uuidv4();
    // 验证码文本转为小写
    const code = captcha.text.toLowerCase();
    
    // 存储验证码
    await this.store(uuid, code);
    
    return {
      uuid,
      img: captcha.data
    };
  }

  /**
   * 验证验证码
   * @param uuid 验证码标识
   * @param code 用户输入的验证码
   * @returns 验证结果
   */
  static async validate(uuid: string, code: string): Promise<boolean> {
    if (!uuid || !code) {
      return false;
    }

    // 获取存储的验证码
    const captchaKey = `captcha_codes:${uuid}`;
    // 获取尝试次数键名
    const attemptsKey = `captcha_codes:attempts:${uuid}`;
    
    // 尝试获取当前验证码尝试次数
    let attempts = 0;
    
    if (redisClient) {
      attempts = parseInt(await redisClient.get(attemptsKey) || '0', 10);
      
      // 超过最大尝试次数
      if (attempts >= CAPTCHA_CONFIG.maxAttempts) {
        // 删除验证码和尝试记录
        await redisClient.del(captchaKey);
        await redisClient.del(attemptsKey);
        return false;
      }
      
      // 增加尝试次数
      await redisClient.incr(attemptsKey);
      // 设置尝试次数过期时间
      await redisClient.expire(attemptsKey, CAPTCHA_CONFIG.expire);
      
      // 获取验证码
      const storedCode = await redisClient.get(captchaKey);
      if (!storedCode) {
        return false;
      }
      
      // 验证成功后删除验证码
      if (storedCode.toLowerCase() === code.toLowerCase()) {
        await redisClient.del(captchaKey);
        await redisClient.del(attemptsKey);
        return true;
      }
    } else if (localCache) {
      attempts = localCache.get<number>(attemptsKey) || 0;
      
      // 超过最大尝试次数
      if (attempts >= CAPTCHA_CONFIG.maxAttempts) {
        // 删除验证码和尝试记录
        localCache.del(captchaKey);
        localCache.del(attemptsKey);
        return false;
      }
      
      // 增加尝试次数
      localCache.set(attemptsKey, attempts + 1, CAPTCHA_CONFIG.expire);
      
      // 获取验证码
      const storedCode = localCache.get<string>(captchaKey);
      if (!storedCode) {
        return false;
      }
      
      // 验证成功后删除验证码
      if (storedCode.toLowerCase() === code.toLowerCase()) {
        localCache.del(captchaKey);
        localCache.del(attemptsKey);
        return true;
      }
    }
    
    return false;
  }

  /**
   * 存储验证码
   * @param uuid 验证码标识
   * @param code 验证码文本
   */
  private static async store(uuid: string, code: string) {
    const captchaKey = `captcha_codes:${uuid}`;
    const attemptsKey = `captcha_codes:attempts:${uuid}`;
    
    if (redisClient) {
      // 存储验证码
      await redisClient.set(captchaKey, code);
      // 设置过期时间
      await redisClient.expire(captchaKey, CAPTCHA_CONFIG.expire);
      // 初始化尝试次数
      await redisClient.set(attemptsKey, 0);
      // 设置尝试次数过期时间
      await redisClient.expire(attemptsKey, CAPTCHA_CONFIG.expire);
    } else if (localCache) {
      // 存储验证码
      localCache.set(captchaKey, code, CAPTCHA_CONFIG.expire);
      // 初始化尝试次数
      localCache.set(attemptsKey, 0, CAPTCHA_CONFIG.expire);
    }
  }
}

export default CaptchaUtil; 